/*
 * Tuple.h
 *
 *	Author: stravant
 *	Description:
 *		
 */

#ifndef TUPLE_H_
#define TUPLE_H_

template <class P>
class TupleTraits {
	typedef const P& ParamType;
};

class Tuple0 {
public:
};

template <class A>
class Tuple1 {
public:
	typedef A TypeA;
	Tuple1() {}
	Tuple1(typename TupleTraits<A>::ParamType a): mA(a) {}
	const A& a() {return mA;}
private:
	A mA;
};

template <class A, class B>
class Tuple2 {
public:
	typedef A TypeA;
	typedef B TypeB;
	Tuple2() {}
	Tuple2(typename TupleTraits<A>::ParamType a,
		   typename TupleTraits<B>::ParamType b): mA(a), mB(b) {}
	const A& a() {return mA;}
	const B& b() {return mB;}
private:
	A mA;
	B mB;
};

template <class A, class B, class C>
class Tuple3 {
public:
	typedef A TypeA;
	typedef B TypeB;
	typedef C TypeC;
	Tuple3() {}
	Tuple3(typename TupleTraits<A>::ParamType a,
		   typename TupleTraits<B>::ParamType b,
		   typename TupleTraits<C>::ParamType c): mA(a), mB(b), mC(c) {}
	const A& a() {return mA;}
	const B& b() {return mB;}
	const C& c() {return mC;}
private:
	A mA;
	B mB;
	C mC;
};

inline Tuple0 MakeTuple() {
	return Tuple0();
}

template <class A>
inline Tuple1<A> MakeTuple(A a) {
	return Tuple1<A>(a);
}

template <class A, class B>
inline Tuple2<A,B> MakeTuple(A a, B b) {
	return Tuple2<A,B>(a, b);
}

template<class A, class B, class C>
inline Tuple3<A,B,C> MakeTuple(A a, B b, C c) {
	return Tuple3<A,B,C>(a, b, c);
}

template <class ObjT, class Method>
inline void DispatchToMethod(ObjT* obj, Method method, const Tuple0& arg) {
	(obj->*method)();
}

template <class ObjT, class Method, class A>
inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) {
	(obj->*method)(arg);
}

template <class ObjT, class Method, class A>
inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1<A>& arg) {
	(obj->*method)(arg.a());
}

template <class ObjT, class Method, class A, class B>
inline void DispatchToMethod(ObjT* obj, Method method, const Tuple2<A,B>& arg) {
	(obj->*method)(arg.a(), arg.b());
}

template <class ObjT, class Method, class A, class B, class C>
inline void DispatchToMethod(ObjT* obj, Method method, const Tuple3<A,B,C>& arg) {
	(obj->*method)(arg.a(), arg.b(), arg.c());
}


#endif /* TUPLE_H_ */


















